﻿/*********************************************************************************
 *Author:         OnClick
 *Version:        0.0.2.51
 *UnityVersion:   2018.4.24f1
 *Date:           2020-09-13
 *Description:    IFramework
 *History:        2018.11--
*********************************************************************************/
using UnityEditor;
using IFramework.GUITool;
using System;
using UnityEngine;
using System.IO;
using UnityEngine.Networking;
using System.Collections.Generic;
using IFramework.GUITool.ToorbarMenu;
using System.Linq;
using UnityEditor.IMGUI.Controls;

#pragma warning disable
namespace IFramework
{
    partial class RootWindow : EditorWindow
    {
        static class PkgsTool
        {
            public enum ErrorCode
            {
                Sucess = 200,
            }
            static class Urls
            {
                public const string host = "https://www.aicxz.com/api/v1";
                public const string login = host + "/User/Login";
                public const string loginWithToken = host + "/User/LoginWithToken";
                public const string putpackage = host + "/Pkg/PutPkg";
                public const string getpackageList = host + "/Pkg/GetPkglist";
                public const string getpackageInfos = host + "/Pkg/GetPkgInfos";
                public const string getpkgurl = host + "/Pkg/DownLoadPkg";
                public const string deletepackage = host + "/Pkg/DeletePkg";
            }
            public static class Models
            {
                public abstract class ResponseModel
                {
                    public ErrorCode code;
                    public string err;

                    internal static T Dispose<T>(string text) where T : ResponseModel
                    {
                        try
                        {
                            T t = JsonUtility.FromJson<T>(text);
                            return t;
                        }
                        catch (Exception)
                        {
                            _window.ShowNotification(new GUIContent("数据解析错误"));
                            return null;
                        }
                    }

                    internal bool CheckCode()
                    {
                        if (code != ErrorCode.Sucess)
                        {
                            _window.ShowNotification(new GUIContent(code.ToString() + err));
                        }
                        return code == ErrorCode.Sucess;
                    }
                }
                public abstract class TokenModel : ResponseModel
                {
                    public string token;
                }

                public class LoginModel : TokenModel
                {
                    public string name;
                }

                public class PutPackageModel : ResponseModel { }
                [Serializable]
                public class PackageListModel : ResponseModel
                {
                    [Serializable]
                    public class PkgShort
                    {
                        public string name;
                        public string author;
                        public string versions;
                        public DateTime time;
                    }
                    public PkgShort[] pkgs = new PkgShort[0];
                }
                [Serializable]
                public class PackageInfosModel : ResponseModel
                {
                    public string name;
                    public string author;

                    public List<VersionInfo> versions = new List<VersionInfo>();
                    [Serializable]
                    public class VersionInfo
                    {
                        public bool preview;
                        public string version;
                        public string describtion;
                        public string dependences;
                        public string assetPath;
                    }

                }
                public class DeletePackageModel : ResponseModel { }
            }
     

           public  class LocalPkgVersions
            {
                [System.Serializable]
                public class PkgVersion
                {
                    public string name;
                    public string version;
                }
                private static LocalPkgVersions _localVersions;
                private static LocalPkgVersions Instance
                {
                    get
                    {

                        if (_localVersions == null)
                        {
                            if (!File.Exists(Paths.localVersionsPath))
                            {
                                File.WriteAllText(Paths.localVersionsPath, JsonUtility.ToJson(new LocalPkgVersions(), true));
                            }
                            _localVersions = JsonUtility.FromJson<LocalPkgVersions>(File.ReadAllText(Paths.localVersionsPath));
                        }
                        return _localVersions;
                    }
                }
                [SerializeField]private List<PkgVersion> versions = new List<PkgVersion>();
                public static void UpdateLocalVersion(string name, string version)
                {
                    var tmp = Instance.versions.Find((o) => { return o.name == name; });
                    if (tmp == null)
                    {
                        Instance.versions.Add(new LocalPkgVersions.PkgVersion() { name = name, version = version });
                    }
                    else
                    {
                        tmp.version = version;
                    }
                    File.WriteAllText(Paths.localVersionsPath, JsonUtility.ToJson(Instance, true));
                    AssetDatabase.Refresh();
                    InvokePkgsFresh();
                }
                public static string GetLocalVersion(string name)
                {
                    var tmp = Instance.versions.Find((o) => { return o.name == name; });
                    if (tmp == null) return string.Empty;
                    return tmp.version;
                }
            }
            static class Requests
            {
                private abstract class Request
                {
                    public readonly string url;
                    private readonly Action<UnityWebRequest> _callback;
                    protected UnityWebRequest request;
                    public float progress { get { return request.downloadProgress; } }
                    public bool isDone { get { return request.isDone; } }
                    protected Request(string url, Action<UnityWebRequest> callback)
                    {
                        this.url = url;
                        this._callback = callback;
                    }

                    public void Start()
                    {
                        request.SendWebRequest();
                    }

                    public void Compelete()
                    {
                        EditorUtility.ClearProgressBar();
                        if (!string.IsNullOrEmpty(request.error))
                        {
                            _window.ShowNotification(new GUIContent(request.error));
                            return;
                        }
                        if (_callback != null)
                        {
                            _callback.Invoke(request);
                        }
                        request.Abort();
                        request.Dispose();
                    }
                    public static long GetTimeStamp(bool bflag = true)
                    {
                        TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                        long ret;
                        if (bflag)
                            ret = Convert.ToInt64(ts.TotalSeconds);
                        else
                            ret = Convert.ToInt64(ts.TotalMilliseconds);
                        return ret;
                    }
                }
                private class Request_Get : Request
                {
                    public Request_Get(string url, Action<UnityWebRequest> callback, Dictionary<string, object> forms) : base(url, callback)
                    {
                        string newUrl = url;
                        if (forms != null && forms.Count > 0)
                        {
                            newUrl += "?";
                            foreach (var item in forms)
                            {
                                newUrl += string.Format("{0}={1}", item.Key, item.Value) + "&";
                            }
                            newUrl += GetTimeStamp();
                        }
                        else
                        {
                            newUrl += "?" + GetTimeStamp();
                        }
                        request = UnityWebRequest.Get(newUrl);
                    }
                }
                private class Request_Post : Request
                {
                    public Request_Post(string url, Action<UnityWebRequest> callback, WWWForm forms) : base(url, callback)
                    {
                        if (forms == null)
                        {
                            forms = new WWWForm();
                        }
                        url += "?" + GetTimeStamp();
                        request = UnityWebRequest.Post(url, forms);
                    }
                }
                private const int maxRequest = 20;
                private static Queue<Request> _waitRequests;
                private static List<Request> _requests;
                private static void Update()
                {
                    if (_waitRequests.Count <= 0 && _requests.Count <= 0) return;
                    while (_requests.Count < maxRequest && _waitRequests.Count > 0)
                    {
                        var _req = _waitRequests.Dequeue();
                        _req.Start();
                        _requests.Add(_req);
                    }

                    for (int i = _requests.Count - 1; i >= 0; i--)
                    {
                        var _req = _requests[i];
                        if (_req.isDone)
                        {
                            _req.Compelete();
                            _requests.Remove(_req);
                            //  break;
                        }
                        else
                        {
                            EditorUtility.DisplayProgressBar("Post Request", _req.url, _req.progress);
                        }
                    }
                }
                private static void Run(Request request)
                {
                    if (_waitRequests == null)
                    {
                        _waitRequests = new Queue<Request>();
                        _requests = new List<Request>();
                        EditorEnv.env.BindUpdate(Update);
                    }
                    _waitRequests.Enqueue(request);
                }



                public static void GetRequest(string url, Dictionary<string, object> forms, Action<UnityWebRequest> callback)
                {
                    Run(new Request_Get(url, callback, forms));
                }
                public static void PostRequest(string url, WWWForm forms, Action<UnityWebRequest> callback)
                {
                    Run(new Request_Post(url, callback, forms));
                }
                private static void GetRequest<T>(string url, Dictionary<string, object> forms, Action<T> callback) where T : Models.ResponseModel
                {
                    GetRequest(url, forms, (req) =>
                    {
                        T t = Models.ResponseModel.Dispose<T>(req.downloadHandler.text);
                        if (t == null) return;
                        bool bo = t.CheckCode();
                        if (callback != null) callback.Invoke(t);
                    });
                }
                private static void PostRequest<T>(string url, WWWForm forms, Action<T> callback) where T : Models.ResponseModel
                {
                    PostRequest(url, forms, (req) =>
                    {
                        T t = Models.ResponseModel.Dispose<T>(req.downloadHandler.text);
                        if (t == null) return;
                        bool bo = t.CheckCode();
                        if (callback != null) callback.Invoke(t);
                    });
                }



                public static void Login(string email, string password, Action<Models.LoginModel> callback)
                {
                    WWWForm www = new WWWForm();
                    www.AddField("email", email);
                    www.AddField("password", password);
                    PostRequest<Models.LoginModel>(Urls.login, www, (m) =>
                    {
                        if (callback != null) callback(m);
                    });
                }
                public static void Login(string token, Action<Models.LoginModel> callback)
                {
                    WWWForm www = new WWWForm();
                    www.AddField("token", token);
                    PostRequest<Models.LoginModel>(Urls.loginWithToken, www, (m) =>
                    {
                        if (callback != null) callback(m);
                    });
                }
                public static void PutPackage(string name, string author, string version, string describtion, bool preview, string dependences, string assetpath, byte[] buffer, Action<Models.PutPackageModel> callback)
                {
                    WWWForm www = new WWWForm();
                    www.AddField("name", name);
                    www.AddField("author", author);
                    www.AddField("version", version);
                    www.AddField("describtion", describtion);
                    www.AddField("assetpath", assetpath);
                    www.AddField("preview", preview.ToString());
                    www.AddField("dependences", dependences);
                    www.AddBinaryData("buffer", buffer);
                    PostRequest<Models.PutPackageModel>(Urls.putpackage, www, (m) =>
                    {
                        if (callback != null) callback(m);
                    });
                }
                public static void GetPackageList(Action<Models.PackageListModel> callback)
                {
                    PostRequest<Models.PackageListModel>(Urls.getpackageList, null, (m) =>
                    {
                        if (callback != null) callback(m);
                    });
                }
                public static void GetPkgInfos(string name, Action<Models.PackageInfosModel> callback)
                {
                    WWWForm www = new WWWForm();
                    www.AddField("name", name);
                    PostRequest<Models.PackageInfosModel>(Urls.getpackageInfos, www, (m) =>
                    {
                        if (callback != null) callback(m);
                    });
                }
                public static void DownLoadPkg(string name, string version, Action<UnityWebRequest> callback)
                {
                    WWWForm www = new WWWForm();
                    www.AddField("name", name);
                    www.AddField("version", version);
                    PostRequest(Urls.getpkgurl, www, (m) =>
                    {
                        if (callback != null) callback(m);
                    });
                }
                public static void DeletePkg(string author, string name, string version, Action<Models.DeletePackageModel> callback)
                {
                    WWWForm www = new WWWForm();
                    www.AddField("author", author);
                    www.AddField("name", name);
                    www.AddField("version", version);
                    PostRequest<Models.DeletePackageModel>(Urls.deletepackage, www, (m) =>
                    {
                        if (callback != null) callback(m);
                    });
                }
            }

            public class LoginInfo
            {
                public string email;
                public string password;
            }
            public class UploadInfo
            {
                public string name;
                public int[] version = new int[4];
                public string assetPath;
                public string describtion = "No Describtion";
                public bool preview;
                public string[] dependences = new string[0];
                public byte[] buffer;
            }

            private static class Paths
            {
                public static string rootPath { get { return EditorEnv.memoryPath; } }

                public static string userjsonPath { get { return rootPath + "/user.json"; } }
                public static string localVersionsPath { get { return EditorEnv.projectMemoryPath + "/localVersions.json"; } }
                public static string pkgjsonPath { get { return rootPath + "/pkgs.json"; } }
                public static string pkgversionjsonPath
                {
                    get
                    {
                        string path = rootPath + "/pkgversion";
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }
                        return path;
                    }
                }
                public static string pkgPath
                {
                    get
                    {
                        string path = rootPath + "/pkgs";
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }
                        return path;
                    }
                }
                public static string localPkgPath
                {
                    get
                    {
                        string path = rootPath + "/localpkgs";
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }
                        return path;
                    }
                }
            }
            public class PkgkitData
            {
                public class UserJson
                {
                    public string name;
                    public string token;
                }
                private List<PkgsTool.Models.PackageInfosModel> pkgInfos = new List<PkgsTool.Models.PackageInfosModel>();
                private UserJson _userJson = new UserJson();
                private static PkgkitData _instance;
                private static PkgkitData instance
                {
                    get
                    {
                        if (_instance == null)
                        {
                            _instance = new PkgkitData();
                        }
                        return _instance;
                    }
                }

                public static bool login
                {
                    get
                    {
                        if (instance._userJson == null) return false;
                        if (string.IsNullOrEmpty(instance._userJson.name)) return false;
                        return true;
                    }
                }
                public static UserJson userJson { get { return instance._userJson; } }
                public static bool ReadUserJson()
                {
                    if (File.Exists(Paths.userjsonPath))
                    {
                        instance._userJson = JsonUtility.FromJson<PkgkitData.UserJson>(File.ReadAllText(Paths.userjsonPath));
                        return true;
                    }
                    else {
                        instance._userJson = new UserJson();
                        return false;
                    }
                }
                public static void ClearUserJson()
                {
                    instance._userJson = new PkgkitData.UserJson();
                    if (File.Exists(Paths.userjsonPath))
                    {
                        File.Delete(Paths.userjsonPath);
                    }
                }
                public static void WriteUserJson(string name, string token)
                {
                    instance._userJson = new PkgkitData.UserJson()
                    {
                        name = name,
                        token = token
                    };
                    File.WriteAllText(Paths.userjsonPath, JsonUtility.ToJson(instance._userJson, true));
                }

                public static void ClearPkgs()
                {
                    instance.pkgInfos.Clear();
                }
                public static void AddPkg(Models.PackageInfosModel info,int max)
                {
                    instance.pkgInfos.Add(info);
                    if (max <= instance.pkgInfos.Count)
                    {
                        InvokePkgsFresh();
                    }
                }
                public static List<string> GetPkgNames()
                {
                   return instance.pkgInfos.ConvertAll((p) => { return p.name; });
                }
                public static PkgsTool.Models.PackageInfosModel GetPkg(string name)
                {
                    return instance.pkgInfos.Find((_p) => { return _p.name == name; });
                }
                public static List<PkgsTool.Models.PackageInfosModel> GetSelfPkgs()
                {
                    return instance.pkgInfos.FindAll((p) => { return p.author == instance._userJson.name; });
                }
            }
            private static event Action onFreshpkgs;
            public static void ListenPkgsChange(Action action)
            {
                if (action!=null)
                {
                    onFreshpkgs += action;
                }
            }
            public static void InvokePkgsFresh()
            {
                if (onFreshpkgs!=null)
                {
                    onFreshpkgs.Invoke();
                }
            }

            public static void OpenMemory()
            {
                EditorTools.OpenFolder(Paths.rootPath);
            }
            public static void ClearMemory()
            {
                Logout();
                Directory.Delete(Paths.rootPath, true);
            }

            public static void Logout()
            {
                PkgkitData.ClearUserJson();
            }
           
            public static void FreshWebPackages()
            {
                PkgkitData.ClearPkgs();
            
                Requests.GetPackageList((m) =>
                {
                    if (m.code != ErrorCode.Sucess) return;

                    Models.PackageListModel local = new Models.PackageListModel();
                    if (File.Exists(Paths.pkgjsonPath))
                    {
                        local = JsonUtility.FromJson<Models.PackageListModel>(File.ReadAllText(Paths.pkgjsonPath));
                    }
                    File.WriteAllText(Paths.pkgjsonPath, JsonUtility.ToJson(m));
                    var localPkgs = local.pkgs.ToList();
                    if (m.pkgs.Length == 0)
                    {
                        InvokePkgsFresh();
                    }
                    for (int i = 0; i < m.pkgs.Length; i++)
                    {
                        var p = m.pkgs[i];
                        var tmp = localPkgs.Find((_p) => { return p.versions == _p.versions && _p.name == p.name && _p.time == p.time && p.author == _p.author; });
                        localPkgs.Remove(tmp);
                        string path = Path.Combine(Paths.pkgversionjsonPath, p.name + ".json");
                        if (tmp != null)
                        {
                            if (File.Exists(path))
                            {
                                PkgkitData.AddPkg(JsonUtility.FromJson<Models.PackageInfosModel>(File.ReadAllText(path)), m.pkgs.Length);
                            }
                            else
                            {
                                Requests.GetPkgInfos(p.name, (model) =>
                                {
                                    PkgkitData.AddPkg(model, m.pkgs.Length);
                                    File.WriteAllText(path, JsonUtility.ToJson(model, true));
                                });
                            }
                        }
                        else
                        {
                            Requests.GetPkgInfos(p.name, (model) =>
                            {
                                PkgkitData.AddPkg(model, m.pkgs.Length);
                                File.WriteAllText(path, JsonUtility.ToJson(model, true));
                            });
                        }
                    }
                    localPkgs.ForEach((_p) =>
                    {
                        string path = Path.Combine(Paths.pkgversionjsonPath, _p.name + ".json");
                        if (File.Exists(path))
                        {
                            File.Delete(path);
                        }
                    });
                });
            }

            public static void Init()
            {
                if (PkgkitData.ReadUserJson())
                {
                    Requests.Login(PkgkitData.userJson.token, (m) =>
                    {
                        if (m.code != ErrorCode.Sucess)
                        {
                            Logout();
                        }
                        else
                        {
                            PkgkitData.WriteUserJson(m.name, m.token);
                        }
                            FreshWebPackages();
                    });
                }
                else
                {
                    FreshWebPackages();
                }
            }

            public static void Login(LoginInfo info)
            {
                Requests.Login(info.email, info.password, (m) =>
                {
                    if (m.code != ErrorCode.Sucess)
                    {
                        Logout();
                    }
                    else
                    {
                        PkgkitData.WriteUserJson(m.name, m.token);
                        FreshWebPackages();
                    }
                });
            }

            public static void UploadPkg(UploadInfo info)
            {
                if (!PkgkitData.login) return;
                string file = string.Format("{0}_{1}.unitypackage", info.name, string.Join(".", info.version));
                string path = Path.Combine(Paths.localPkgPath, file);
                LocalPkgVersions.UpdateLocalVersion(info.name, string.Join(".", info.version));
                AssetDatabase.ExportPackage(info.assetPath, path, ExportPackageOptions.Recurse);
                info.buffer = File.ReadAllBytes(path);
                Requests.PutPackage(info.name,
                    PkgkitData.userJson.name,
                    string.Join(".", info.version),
                    info.describtion, info.preview,
                    string.Join("@", info.dependences),
                    info.assetPath, info.buffer,
                    (m) => {
                        if (m.code != ErrorCode.Sucess) return;
                        _window.ShowNotification(new GUIContent("上传成功"));
                        FreshWebPackages();
                    });
            }
            public static void DownLoadPkg(string name, string version)
            {
                if (LocalPkgVersions.GetLocalVersion(name) == version) return;
                string path = Path.Combine(Paths.pkgPath, string.Format("{0}_{1}.unitypackage", name, version));
                string path2= Path.Combine(Paths.localPkgPath, string.Format("{0}_{1}.unitypackage", name, version));
                if (File.Exists(path))
                {
                    AssetDatabase.ImportPackage(path, true);
                    LocalPkgVersions.UpdateLocalVersion(name, version);
                    GUIUtility.ExitGUI();
                }
                else if (File.Exists(path2))
                {
                    AssetDatabase.ImportPackage(path2, true);
                    LocalPkgVersions.UpdateLocalVersion(name, version);
                    GUIUtility.ExitGUI();
                }
                else
                {
                    Requests.DownLoadPkg(name, version, (req) =>
                    {
                        path = Path.Combine(Paths.pkgPath, string.Format("{0}_{1}.unitypackage", name, version));
                        File.WriteAllBytes(path, req.downloadHandler.data);
                        path = Path.Combine(Paths.pkgPath, string.Format("{0}_{1}.unitypackage", name, version));
                        AssetDatabase.ImportPackage(path, true);
                        LocalPkgVersions.UpdateLocalVersion(name, version);
                    });
                }
            }
            public static void DeletePkg(string name, string version)
            {
                if (!PkgkitData.login) return;
                if (EditorUtility.DisplayDialog("Make Sure", string.Format("Confirm to delete the pkg in sever \nName:   {0}\nVersion:   {1}", name, version), "Yes", "Cancel"))
                {
                    Requests.DeletePkg(PkgkitData.userJson.name, name, version, (m) =>
                    {
                        if (m.code != ErrorCode.Sucess) return;

                        _window.ShowNotification(new GUIContent("删除成功"));
                        FreshWebPackages();
                    });
                }
            }
            public static void RemoveLocalPkg(string name, string assetPath)
            {
                if (EditorUtility.DisplayDialog("Make Sure", string.Format("Confirm to delete the pkg in project \nName:   {0}\nAssetPath:   {1}", name, assetPath), "Yes", "Cancel"))
                {
                    Directory.Delete(assetPath, true);
                    LocalPkgVersions.UpdateLocalVersion(name, "");
                    AssetDatabase.Refresh();
                }

            }

        }

    }
    partial class RootWindow 
    {

        class UserOptionWindow
        {

            public enum UserOperation
            {
                ProjectConfig, WindowCollection, Account, Pkg_Upload,Other
            }

            class SystemGUI
            {
                public void OnGUI()
                {
                    GUILayout.BeginVertical("Box");

                    GUILayout.Label("操作系统：" + SystemInfo.operatingSystem);
                    GUILayout.Label("系统内存：" + SystemInfo.systemMemorySize + "MB");
                    GUILayout.Label("处理器：" + SystemInfo.processorType);
                    GUILayout.Label("处理器数量：" + SystemInfo.processorCount);
                    GUILayout.Label("显卡：" + SystemInfo.graphicsDeviceName);
                    GUILayout.Label("显卡类型：" + SystemInfo.graphicsDeviceType);
                    GUILayout.Label("显存：" + SystemInfo.graphicsMemorySize + "MB");
                    GUILayout.Label("显卡标识：" + SystemInfo.graphicsDeviceID);
                    GUILayout.Label("显卡供应商：" + SystemInfo.graphicsDeviceVendor);
                    GUILayout.Label("显卡供应商标识码：" + SystemInfo.graphicsDeviceVendorID);
                    GUILayout.Label("设备模式：" + SystemInfo.deviceModel);
                    GUILayout.Label("设备名称：" + SystemInfo.deviceName);
                    GUILayout.Label("设备类型：" + SystemInfo.deviceType);
                    GUILayout.Label("设备标识：" + SystemInfo.deviceUniqueIdentifier);

                    GUILayout.Label("DPI：" + Screen.dpi);
                    GUILayout.Label("分辨率：" + Screen.currentResolution.ToString());
                    GUILayout.EndVertical();


                    GUILayout.FlexibleSpace();
                    GUILayout.BeginHorizontal();
                    {
                        if (GUILayout.Button("Open Memory "))
                        {
                            PkgsTool.OpenMemory();
                        }
                        if (GUILayout.Button("Clear Memory "))
                        {
                            PkgsTool.ClearMemory();
                        }

                        GUILayout.EndHorizontal();
                    }

                    GUILayout.BeginHorizontal();
                    {
                        OpenFolderGUI("Open Doc", Application.persistentDataPath);
                        OpenFolderGUI("Open Streaming", Application.streamingAssetsPath);
                        OpenFolderGUI("Open DataPath", Application.dataPath);
                        OpenFolderGUI("Open Temporary", Application.temporaryCachePath);

                        GUILayout.EndHorizontal();
                    }

#if UNITY_2018_1_OR_NEWER

                    OpenFolderGUI("Open Console", Application.consoleLogPath);

#endif
                    GUILayout.Space(10);
                }
                private void OpenFolderGUI(string name, string path)
                {
                    if (GUILayout.Button(name))
                    {
                        EditorTools.OpenFolder(path);
                    }
                }
            }

            class LoginGUI
            {
                private class SelectTree : TreeView
                {
                    class Temp
                    {
                        public string name;
                        public string version;
                    }
                    public SelectTree(TreeViewState state, MultiColumnHeader multiColumnHeader) : base(state, multiColumnHeader)
                    {
                        this.rowHeight = 20;
                        showAlternatingRowBackgrounds = true;

                    }
                    public void Fresh()
                    {
                        var pkgs = PkgsTool.PkgkitData.GetSelfPkgs();
                        tmps.Clear();
                        pkgs.ForEach((p) => {
                            for (int i = 0; i < p.versions.Count; i++)
                            {
                                tmps.Add(new Temp()
                                {
                                    name = p.name,
                                    version = p.versions[i].version
                                });
                            }
                        });
                        Reload();
                    }

                    protected override TreeViewItem BuildRoot()
                    {
                        var root = new TreeViewItem { id = 0, depth = -1, displayName = "Root" };
                        return root;
                    }
                    protected override IList<TreeViewItem> BuildRows(TreeViewItem root)
                    {
                        List<TreeViewItem> list = new List<TreeViewItem>();
                        for (int i = 0; i < tmps.Count; i++)
                        {

                            list.Add(new TreeViewItem() { depth = 1, id = i, displayName = i.ToString() });
                        }
                        return list;
                    }
                    List<Temp> tmps = new List<Temp>();

                    protected override void RowGUI(RowGUIArgs args)
                    {
                        var info = tmps[args.item.id];

                        for (int i = 0; i < args.GetNumVisibleColumns(); i++)
                        {
                            switch (i)
                            {
                                case 0:
                                    if (GUI.Button(args.GetCellRect(i), "", GUIStyles.minus))
                                    {
                                        PkgsTool.DeletePkg(info.name, info.version);
                                    }
                                    break;
                                case 1:
                                    GUI.Label(args.GetCellRect(i), info.name);
                                    break;
                                case 2:
                                    GUI.Label(args.GetCellRect(i), info.version);
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
                private PkgsTool.LoginInfo _login = new PkgsTool.LoginInfo();
                private SelectTree _tree;
                public LoginGUI()
                {
                    TreeViewState _state = new TreeViewState();
                    _tree = new SelectTree(_state, new MultiColumnHeader(new MultiColumnHeaderState(new MultiColumnHeaderState.Column[] {
                        new MultiColumnHeaderState.Column(){
                            width=20,
                            maxWidth=20,
                            minWidth=20,
                            autoResize =false
                        },
                        new MultiColumnHeaderState.Column()
                        {
                           headerContent=new GUIContent("name"),
                           width=200
                        },
                        new MultiColumnHeaderState.Column(){
                             headerContent=new GUIContent("version"),
                             width=200
                        }
                    })));
                    PkgsTool.ListenPkgsChange(FreshTree);
                    FreshTree();
                }

                private void FreshTree()
                {
                    _tree.Fresh();
                }

                public void OnGUI(Rect position)
                {
                    if (PkgsTool.PkgkitData.login)
                    {
                        position.position = new Vector2(0, 0);
                        _tree.OnGUI(position);
                    }
                    else
                    {
                        _login.email = EditorGUILayout.TextField("Email", _login.email);
                        _login.password = EditorGUILayout.TextField("Password", _login.password);
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.Space();
                        if (GUILayout.Button(Contents.go, GUILayout.Width(Contents.gap * 5)))
                        {
                            PkgsTool.Login(_login);
                        }
                        EditorGUILayout.EndHorizontal();
                    }

                }
            }
            class ProjectConfigGUI
            {
                static class Contents
                {
                    public static GUIContent Name = new GUIContent("UserName", "Project Author's Name");
                    public static GUIContent Version = new GUIContent("Version", "Version of Project");
                    public static GUIContent Namespace = new GUIContent("NameSpace_ProductName", "Script's Namespace and ProductName");
                    public static GUIContent Describe = new GUIContent("Description of Scripts");
                    public static string logset = "LogSetting in Editor mode";
                    public static string enable = "Enable";
                    public static string logenable = "Log Enable";
                    public static string wenable = "Warning Enable";
                    public static string errenable = "Error Enable";
                }
                public void OnGUI()
                {
                    var Info = EditorTools.ProjectConfig.Info;
                    GUILayout.Space(10);
                    EditorGUI.BeginChangeCheck();
                    GUI.enabled = false;
                    Info.UserName = EditorGUILayout.TextField(Contents.Name, PkgsTool.PkgkitData.userJson.name);
                    GUI.enabled = true;
                    Info.Version = EditorGUILayout.TextField(Contents.Version, Info.Version);
                    Info.NameSpace= EditorGUILayout.TextField(Contents.Namespace, Info.NameSpace);
                    GUILayout.Label(Contents.Describe);
                    Info.Description = EditorGUILayout.TextArea(Info.Description, GUILayout.Height(100));
                    GUILayout.Space(10);
                    EditorGUI.DrawRect(EditorGUILayout.GetControlRect(GUILayout.Height(2)), new Color(0.5f, 0.5f, 0.5f));
                    GUILayout.Label(Contents.logset, GUIStyles.largeLabel);
                    Info.enable = EditorGUILayout.Toggle(Contents.enable, Info.enable);
                    GUI.enabled = Info.enable;
                    Info.enable_L = EditorGUILayout.Toggle(Contents.logenable, Info.enable_L);
                    Info.enable_W = EditorGUILayout.Toggle(Contents.wenable, Info.enable_W);
                    Info.enable_E = EditorGUILayout.Toggle(Contents.errenable, Info.enable_E);

                    if (EditorGUI.EndChangeCheck())
                    {
                        EditorTools.ProjectConfig.Save();
                    }  
                    GUI.enabled = true;
                }
            }
            class UploadGUI
            {
                private PkgsTool.UploadInfo _upload = new PkgsTool.UploadInfo();
                private FloderField _floderField = new FloderField();
                public UploadGUI()
                {
                    _floderField.onValueChange += (value) => {
                        if (!string.IsNullOrEmpty(value) && value.Contains("Assets"))
                        {
                            _upload.assetPath = value.ToAssetsPath();
                            _upload.name = Path.GetFileNameWithoutExtension(_upload.assetPath);
                            _floderField.SetPath(_upload.assetPath);
                        }
                    };
                }
                private Vector2 scroll;
                public void OnGUI()
                {
                    scroll = GUILayout.BeginScrollView(scroll);
                    EditorGUILayout.LabelField("Author", PkgsTool.PkgkitData.userJson.name);
                    _upload.name = EditorGUILayout.TextField("Name", _upload.name);
                    _upload.preview = EditorGUILayout.Toggle("Preview", _upload.preview);
                    {
                        GUILayout.BeginHorizontal();
                        GUILayout.Label("Version");
                        GUILayout.Space(100);
                        for (int i = 0; i < _upload.version.Length; i++)
                        {
                            _upload.version[i] = EditorGUILayout.IntField(_upload.version[i]);
                            if (i < _upload.version.Length - 1)
                            {
                                GUILayout.Label(".", GUILayout.Width(Contents.gap));
                            }
                        }
                        GUILayout.EndHorizontal();
                    }

                    {
                        EditorGUILayout.LabelField("AssetPath","");
                        var rect = GUILayoutUtility.GetLastRect();
                        rect.xMin = rect.xMin + 150;
                        _floderField.OnGUI(rect);
                       
                    }

                    GUILayout.Label("Dependences", GUIStyles.BoldLabel);
                    for (int i = 0; i < _upload.dependences.Length; i++)
                    {
                        GUILayout.BeginHorizontal();
                        _upload.dependences[i] = EditorGUILayout.TextField(_upload.dependences[i]);
                        if (GUILayout.Button("", GUIStyles.minus, GUILayout.Width(18)))
                        {
                            ArrayUtility.RemoveAt(ref _upload.dependences, i);
                        }
                        GUILayout.EndHorizontal();
                    }
                    GUILayout.BeginHorizontal();
                    GUILayout.FlexibleSpace();
                    if (GUILayout.Button("", GUIStyles.plus))
                    {
                        ArrayUtility.Add(ref _upload.dependences, "");
                    }
                    GUILayout.EndHorizontal();

                    GUILayout.Label("Describtion", GUIStyles.BoldLabel);
                    _upload.describtion = EditorGUILayout.TextArea(_upload.describtion,GUIStyles.textArea_rich,GUILayout.MaxHeight(Contents.gap * 10));

                    {
                        GUILayout.BeginHorizontal();
                        using (new EditorGUI.DisabledScope(string.IsNullOrEmpty(GUIUtility.systemCopyBuffer)))
                        {
                            if (GUILayout.Button("Paste", GUILayout.Width(Contents.gap * 5)))
                            {
                                try
                                {
                                    var p = JsonUtility.FromJson<PkgsTool.Models.PackageInfosModel>(GUIUtility.systemCopyBuffer);
                                    _upload.describtion = p.versions.Last().describtion;
                                    var str_dp = p.versions.Last().dependences;
                                    if (!string.IsNullOrEmpty(str_dp))
                                        _upload.dependences = str_dp.Split('@'); 
                                    _upload.name = p.name;
                                    _upload.preview = p.versions.Last().preview;
                                    _upload.assetPath = p.versions.Last().assetPath;
                                    _floderField.SetPath(_upload.assetPath);
                                    var vs = p.versions.Last().version.Split('.');
                                    for (int i = 0; i < _upload.version.Length; i++)
                                    {
                                        _upload.version[i] = int.Parse(vs[i]);
                                        if (i == _upload.version.Length - 1)
                                        {
                                            _upload.version[i]++;
                                        }
                                    }
                                    for (int i = _upload.version.Length - 1; i > 0; i--)
                                    {
                                        if (_upload.version[i] >= 100)
                                        {
                                            _upload.version[i] = 1;
                                            _upload.version[i - 1]++;
                                        }
                                    }
                                    GUI.FocusControl("");
                                }
                                catch (Exception) { }

                            }
                        }

                        GUILayout.FlexibleSpace();
                        if (GUILayout.Button(Contents.go, GUILayout.Width(Contents.gap * 5)))
                        {
                            PkgsTool.UploadPkg(_upload);
                        }
                        GUILayout.EndHorizontal();
                    }
                    GUILayout.EndScrollView();
                }
            }
            class WindowCollection
            {
                private class SelectTree : TreeView
                {
                    private struct Index
                    {
                        public int id;
                        public EditorWindowTool.Entity value;
                    }
                    private List<Index> _show;
                    public SelectTree(TreeViewState state) : base(state)
                    {
                        this.rowHeight = 22;
                        EditorWindowTool.windows.FindAll((w) => { return w.searchName.ToLower().Contains(_window.search); }).ToArray();
                        _show = new List<Index>();
                        EditorWindowTool.windows
                            .ForEach((entity) =>
                            {
                                _show.Add(new Index() { value = entity, id = EditorWindowTool.windows.IndexOf(entity) });
                            });
                        showAlternatingRowBackgrounds = true;

                        Reload();
                    }
                    protected override void DoubleClickedItem(int id)
                    {
                        var w = EditorWindowTool.FindOrCreate(_show.Find((index) => { return index.id == id; }).value.searchName);
                        if (w != null)
                        {
                            w.Focus();
                        }
                    }
                    protected override TreeViewItem BuildRoot()
                    {
                        var root = new TreeViewItem { id = -1, depth = -1, displayName = "Root" };
                        return root;
                    }
                    protected override void SearchChanged(string newSearch)
                    {
                        _show.Clear();
                        EditorWindowTool.windows.FindAll((w) => { return w.searchName.ToLower().Contains(_window.search); })
                            .ForEach((entity) =>
                            {
                                _show.Add(new Index() { value = entity, id = EditorWindowTool.windows.IndexOf(entity) });

                            });
                        Reload();
                    }
                    protected override IList<TreeViewItem> BuildRows(TreeViewItem root)
                    {
                        List<TreeViewItem> list = new List<TreeViewItem>();
                        for (int i = 0; i < _show.Count; i++)
                        {
                            list.Add(new TreeViewItem() { depth = 1, id = _show[i].id, displayName = _show[i].value.searchName });
                        }
                        return list;
                    }
                    protected override void RowGUI(RowGUIArgs args)
                    {
                        var window = EditorWindowTool.windows[args.item.id];
                        if (!string.IsNullOrEmpty(window.type.Namespace) && window.type.Namespace.Contains("UnityEditor"))
                            GUI.Label(args.rowRect, new GUIContent(window.searchName, tx));
                        else
                            GUI.Label(args.rowRect, window.searchName);
                    }

                }

                public static Texture tx = EditorGUIUtility.IconContent("BuildSettings.Editor.Small").image;
                private SelectTree _tree;
                public WindowCollection()
                {
                    _tree = new SelectTree(new TreeViewState());
                }

                public void OnGUI(Rect position)
                {
                    position.position = Vector2.zero;
                    position = position.Zoom(AnchorType.MiddleCenter, -5);
                    _tree.searchString = _window.search;
                    _tree.OnGUI(position);
                }
            }

     

            public UserOptionWindow()
            {
                _split.fistPan += menu.OnGUI;
                _split.secondPan += ContentGUI;
                menu.ReadTree(Enum.GetNames(typeof(UserOperation)).ToList(), false);
                menu.onCurrentChange += (obj) => {
                    _userOperation = (UserOperation)Enum.Parse(typeof(UserOperation), obj);
                };
            }

            private void ContentGUI(Rect position)
            {
                GUILayout.BeginArea(position);
                switch (_userOperation)
                {

                    case UserOperation.Account:
                        _login.OnGUI(position);
                        break;
                    case UserOperation.Pkg_Upload:
                        GUI.enabled = PkgsTool.PkgkitData.login;
                        _upload.OnGUI();
                        GUI.enabled = true;
                        break;
                    case UserOperation.Other:
                        _sys.OnGUI();
                        break;
                    case UserOperation.ProjectConfig:
                        _pc.OnGUI();
                        break;

                    case UserOperation.WindowCollection:
                        _wc.OnGUI(position);
                        break;
                    default:
                        break;
                }
                GUILayout.EndArea();
            }



            private UserOperation _userOperation;
            private MenuTree menu = new MenuTree();
            private SplitView _split = new SplitView();
            private LoginGUI _login = new LoginGUI();
            private UploadGUI _upload = new UploadGUI();
            private SystemGUI _sys = new SystemGUI();
            private ProjectConfigGUI _pc = new ProjectConfigGUI();
            private WindowCollection _wc = new WindowCollection();
            public void Select(UserOperation operation)
            {
                menu.Select(operation.ToString());
            }
            public void OnGUI(Rect position)
            {
                menu.Fitter(_window.search);
                _split.OnGUI(position);
            }
        }

        class PkgsWindow
        {
            public PkgsWindow()
            {
                _split.fistPan += menu.OnGUI;
                _split.secondPan += ContentGUI;
                menu.onCurrentChange += (name) => {
                    index = 0;
                    _select = PkgsTool.PkgkitData.GetPkg(name);
                    versions = _select.versions.ToList().ConvertAll((v) => { return v.version; }).ToArray();
                };
                PkgsTool.ListenPkgsChange(FreshTree);
                FreshTree();
            }
            private void FreshTree()
            {
                menu.Clear();
                var list = PkgsTool.PkgkitData.GetPkgNames();
                menu.ReadTree(list);
                _select = null;
            }
            private PkgsTool.Models.PackageInfosModel _select;
            string[] versions;
            int index;
           
            Vector2 scroll;
            private void ContentGUI(Rect position)
            {
                if (_select == null) return;
                var version = _select.versions[index];

                GUILayout.BeginArea(position.Zoom(AnchorType.MiddleCenter, -10));
                scroll = GUILayout.BeginScrollView(scroll);
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(_select.name, GUIStyles.header);
                    if (version.preview)
                    {
                        GUILayout.Label("preview");
                    }
                    GUILayout.FlexibleSpace();

                    var localversion = PkgsTool.LocalPkgVersions.GetLocalVersion(_select.name);
                    var lastVersion = _select.versions.Last().version;
                    using (new EditorGUI.DisabledGroupScope(lastVersion == localversion))
                    {
                        if (GUILayout.Button(Contents.newest, GUILayout.Width(Contents.gap * 6)))
                        {
                            PkgsTool.DownLoadPkg(_select.name, _select.versions.Last().version);
                        }
                    }
                    using (new EditorGUI.DisabledGroupScope(_select.versions[index].version == localversion))
                    {
                        if (GUILayout.Button(Contents.install, GUILayout.Width(Contents.gap * 6)))
                        {
                            PkgsTool.DownLoadPkg(_select.name, _select.versions[index].version);
                        }
                    }
                    index = EditorGUILayout.Popup(index, versions,GUILayout.Width(Contents.gap * 6));
                    if (Directory.Exists(version.assetPath))
                    {
                        if (GUILayout.Button(Contents.remove, GUILayout.Width(Contents.gap * 6)))
                        {
                            PkgsTool.RemoveLocalPkg(_select.name, version.assetPath);
                        }
                    }
                    if (PkgsTool.PkgkitData.login && PkgsTool.PkgkitData.userJson.name == _select.author)
                    {
                        if (GUILayout.Button(Contents.delete, GUILayout.Width(Contents.gap * 6)))
                        {
                            PkgsTool.DeletePkg(_select.name, version.version);
                        }
                    }
                    GUILayout.EndHorizontal();

                    GUILayout.Label("Author: " + _select.author, GUIStyles.BoldLabel);
                    GUILayout.Label("Local Version: " + localversion);
                    GUI.backgroundColor = Color.black;

                    GUILayout.Label("Asset Path: " + _select.versions[index].assetPath, GUIStyles.helpBox_bold12);

                    GUILayout.Space(Contents.gap / 2);
					if (!string.IsNullOrEmpty(version.dependences))
					{
                        GUILayout.Label("Dependences", GUIStyles.helpBox_bold12);
                        var strs = version.dependences.Split('@');
                        for (int i = 0; i < strs.Length; i++)
                        {
                            GUILayout.Label(strs[i],GUIStyles.BoldLabel);
                        }
                    }
           

                    GUILayout.Space(Contents.gap / 2);
                    GUILayout.Label("Describtion", GUIStyles.helpBox_bold12);

                    GUILayout.Label(version.describtion,GUIStyles.label_rich);
                    GUILayout.EndArea();

                    GUILayout.EndScrollView();
                }
                    Event e = Event.current;
                    if (position.Contains(e.mousePosition) && e.button == 1)
                    {
                        GenericMenu menu = new GenericMenu();
                        menu.AddItem(new GUIContent("Copy/Name"), false, () => { GUIUtility.systemCopyBuffer = _select.name; });
                        menu.AddItem(new GUIContent("Copy/Author"), false, () => { GUIUtility.systemCopyBuffer = _select.author; });
                        menu.AddItem(new GUIContent("Copy/AssetPath"), false, () => { GUIUtility.systemCopyBuffer = _select.versions[index].assetPath; });
                        menu.AddItem(new GUIContent("Copy/Dependences"), false, () => { GUIUtility.systemCopyBuffer = _select.versions[index].dependences; });
                        menu.AddItem(new GUIContent("Copy/Describtion"), false, () => { GUIUtility.systemCopyBuffer = _select.versions[index].describtion; });
                        menu.AddItem(new GUIContent("Copy/All"), false, () => { GUIUtility.systemCopyBuffer = JsonUtility.ToJson(_select, true); });

                        menu.ShowAsContext();
                        if (e.type != EventType.Layout && e.type != EventType.Repaint)
                        {
                            e.Use();
                        }
                    }


            }

            private MenuTree menu = new MenuTree();
            private SplitView _split = new SplitView();
            public void OnGUI(Rect position)
            {
                menu.Fitter(_window.search);
                _split.OnGUI(position);
            }
        }

        enum WindowType
        {
            UserOption,
            Pkgs,
        }
        class Contents
        {
            public const float lineHeight = 20;
            public const float gap = 10;

            public static GUIContent accop = new GUIContent("Account Operation");

            public static GUIContent go = new GUIContent("Go");
            public static GUIContent logout = new GUIContent("Logout");
            public static GUIContent select = new GUIContent("Select");
            public static GUIContent remove = new GUIContent("Remove");
            public static GUIContent install = new GUIContent("Install");
            public static GUIContent delete = new GUIContent("Delete");

            public static GUIContent newest = new GUIContent("Newset");
            public static GUIContent refresh = EditorGUIUtility.IconContent("TreeEditor.Refresh");
            public static GUIContent help = EditorGUIUtility.IconContent("SoftlockProjectBrowser Icon");

        }


        private static RootWindow _window;
        private UserOptionWindow _userOption;
        private PkgsWindow _pkgs;
        private ToolBarTree _toolBarTree;
        private WindowType __windowType;
        private WindowType _windowType
        {
            get { return __windowType; }
            set
            {
                if (__windowType != value)
                {
                    __windowType = value;
                }
            }
        }

    }
    
    partial class RootWindow
    {
        [MenuItem("Window/IFramework %#i")]
        [MenuItem("Assets/IFramework/RootWindow")]

        static void ShowWindow()
        {
            GetWindow<RootWindow>();
        }
        private void OnEnable()
        {
            this
                .titleContent = new GUIContent("RootWindow");
            _window = this;
            this.minSize= new Vector2(700, 400);
            __windowType = EditorTools.Prefs.GetObject<RootWindow, WindowType>("__windowType");
            _pkgs = new PkgsWindow();
            _userOption = new UserOptionWindow();
            _toolBarTree = new ToolBarTree();
            PkgsTool.Init();
            _toolBarTree.Popup((value) => { _windowType = (WindowType)value; }, typeof(WindowType).GetEnumNames(), (int)_windowType)
                .Space(20)
                .FlexibleSpace()
                .SearchField((value) => { search = value; }, search, 200)
                ;
        }
        private string search = "";
        private void OnDisable()
        {
            EditorTools.Prefs.SetObject<RootWindow, WindowType>("__windowType", __windowType);
        }

        private void ShowButton(Rect rect)
        {
            rect = rect.Zoom(AnchorType.MiddleCenter, 10).MoveLeft(10);
            bool bo = GUI.Button(rect, Contents.help, GUIStyles.BoldLabel);
            GUI.Label(rect.Zoom(AnchorType.UpperRight, -10).MoveRight(2), PkgsTool.PkgkitData.login ? EditorGUIUtility.IconContent("greenLight") : EditorGUIUtility.IconContent("redLight"));

            if (bo)
            {


                GenericMenu menu = new GenericMenu();
                menu.AddItem(new GUIContent("Github"), false, () => { Application.OpenURL("https://github.com/OnClick9927/IFramework"); });
                menu.AddItem(new GUIContent("Document"), false, () => { Application.OpenURL("https://blog.csdn.net/qq_37221502/category_10284376.html"); });
                menu.AddItem(new GUIContent("Bilibli"), false, () => { Application.OpenURL("https://space.bilibili.com/382226675"); });
                menu.AddItem(new GUIContent("Sign in"), false, () => { Application.OpenURL("https://www.aicxz.com/User"); });
                menu.AddItem(new GUIContent("Join us"), false, () => { Application.OpenURL("https://jq.qq.com/?_wv=1027&k=TTSfAM1P"); });
                menu.AddSeparator("");
                if (PkgsTool.PkgkitData.login)
                {
                    menu.AddDisabledItem(new GUIContent("Login"));
                    menu.AddItem(new GUIContent("Logout"), false, () => { PkgsTool.Logout(); });
                }
                else
                {
                    menu.AddItem(new GUIContent("Login"), false, () => {
                        _window._windowType = WindowType.UserOption;
                        _userOption.Select(UserOptionWindow.UserOperation.Account);
                    });
                    menu.AddDisabledItem(new GUIContent("Logout"));
                }
                menu.ShowAsContext();
                GUIUtility.ExitGUI();
            }
        }
        private void OnGUI()
        {
            var rs = this.LocalPosition().HorizontalSplit(20);

            _toolBarTree.OnGUI(rs[0]);

            var r2 = rs[1].Zoom(AnchorType.UpperCenter, -10);
            switch (_windowType)
            {
                case WindowType.UserOption:
                    _userOption.OnGUI(r2);
                    break;
                case WindowType.Pkgs:
                    _pkgs.OnGUI(r2);
                    break;
                default:
                    break;
            }
        }

    }

}
